﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace CommonUtils
{
    public class SyncedList<T> where T : class
    {
        protected static int m_Current = 0;
        private static List<T> m_Items;

        public static List<T> Items
        {
            get { return m_Items; }
            set { m_Items = value; }
        }

        /// <summary>
        /// Adds an item to the list.
        /// </summary>
        /// <param name="item">item to be added.</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void Add(T item)
        {
            if (Items == null)
            {
                Items = new List<T>();
            }

            Items.Add(item);
        }

        /// <summary>
        /// Get an item from the list.
        /// </summary>
        /// <param name="id">item ID</param>
        /// <returns>the requested item, if it exists in the list</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static T GetItem(int id)
        {
            if (Items == null ||
                id < 0 ||
                id >= Items.Count
                )
            {
                return null;
            }
            return Items.ElementAt(id);
        }

        /// <summary>
        /// Remove an item from the list.
        /// </summary>
        /// <param name="item">The item being removed.</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void Remove(T item)
        {
            if (Items == null)
            {
                return;
            }
            FixPointerToCurrent(item);
            Items.Remove(item);
        }

        private static void FixPointerToCurrent(T item)
        {
            if (Items == null)
            {
                return;
            }
            int currentIndex = Items.IndexOf(item);
            if (currentIndex == -1)
            {
                return;
            }
            if (currentIndex < m_Current)
            {
                --m_Current;
            }
            if (currentIndex == Items.Count - 1)
            {
                m_Current = 0;
            }
        }

        /// <summary>
        /// Get the next item in the list.
        /// </summary>
        /// <returns>next item in the list</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static T GetNext()
        {
            if (Items == null)
            {
                return null;
            }
            return GetItem(GetNextIndex());
        }

        /// <summary>
        /// Get the index of the next item in the list.
        /// List items are returned in Round-Robin order.
        /// </summary>
        /// <returns>next index</returns>
        private static int GetNextIndex()
        {
            if (Items == null)
            {
                return 0;
            }
            int tmp = m_Current;
            m_Current = (m_Current + 1) % Items.Count;
            return tmp;
        }

        /// <summary>
        /// Get a copy of the list as array.
        /// </summary>
        /// <returns>A copy of the list array.</returns>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public static T[] GetCopy()
        {
            if (Items == null)
            {
                return null;
            }
            return Items.ToArray();
        }
    }
}
